﻿using System.Runtime.InteropServices;
using TDMS.Net.Internals;

namespace TDMS.Net;

public class TdmsChannel : TdmsObject
{
    public ETdmsDataType DataType { get; }

    public TdmsChannel(IntPtr handle, TdmsChannelGroup parent, string name, string description, ETdmsDataType dataType)
    {
        DataType = dataType;
        Parent = parent;
        Handle = handle;
        Name = name;
        Description = description;
    }

    public TdmsChannel SetValues(byte[] values)
    {
        if (DataType != ETdmsDataType.UInt8) throw new TdmsException("only byte values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");
        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_SetDataValuesUInt8(Handle, values, (ulong)values.Length));
        return this;
    }

    public TdmsChannel SetValues(short[] values)
    {
        if (DataType != ETdmsDataType.Int16) throw new TdmsException("only short values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");

        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_SetDataValuesInt16(Handle, values, (ulong)values.Length));
        return this;
    }

    public TdmsChannel SetValues(int[] values)
    {
        if (DataType != ETdmsDataType.Int32) throw new TdmsException("only int values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");

        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_SetDataValuesInt32(Handle, values, (ulong)values.Length));
        return this;
    }

    public TdmsChannel SetValues(float[] values)
    {
        if (DataType != ETdmsDataType.Float) throw new TdmsException("only float values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");

        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_SetDataValuesFloat(Handle, values, (ulong)values.Length));
        return this;
    }

    public TdmsChannel SetValues(double[] values)
    {
        if (DataType != ETdmsDataType.Double) throw new TdmsException("only double values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");

        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_SetDataValuesDouble(Handle, values, (ulong)values.Length));
        return this;
    }

    public TdmsChannel SetValues(string[] values)
    {
        if (DataType != ETdmsDataType.String) throw new TdmsException("only string values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");

        using var pinned = values.ToPinnedPtr();
        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_SetDataValues(Handle, pinned.PinnedPtr, (ulong)values.Length));
        return this;
    }

    public TdmsChannel AppendValues(byte[] values)
    {
        if (DataType != ETdmsDataType.UInt8) throw new TdmsException("only byte values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");

        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_AppendDataValuesUInt8(Handle, values, (ulong)values.Length));
        return this;
    }

    public TdmsChannel AppendValues(short[] values)
    {
        if (DataType != ETdmsDataType.Int16) throw new TdmsException("only short values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");

        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_AppendDataValuesInt16(Handle, values, (ulong)values.Length));
        return this;
    }

    public TdmsChannel AppendValues(int[] values)
    {
        if (DataType != ETdmsDataType.Int32) throw new TdmsException("only int values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");

        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_AppendDataValuesInt32(Handle, values, (ulong)values.Length));
        return this;
    }

    public TdmsChannel AppendValues(float[] values)
    {
        if (DataType != ETdmsDataType.Float) throw new TdmsException("only float values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");

        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_AppendDataValuesFloat(Handle, values, (ulong)values.Length));
        return this;
    }

    public TdmsChannel AppendValues(double[] values)
    {
        if (DataType != ETdmsDataType.Double) throw new TdmsException("only double values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");

        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_AppendDataValuesDouble(Handle, values, (ulong)values.Length));
        return this;
    }

    public TdmsChannel AppendValues(string[] values)
    {
        if (DataType != ETdmsDataType.String) throw new TdmsException("only string values supported.");
        if (values is null or { Length: 0 }) throw new TdmsException("values can not be empty");
        using var pinned = values.ToPinnedPtr();
        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_AppendDataValues(Handle, pinned.PinnedPtr, (ulong)values.Length));
        return this;
    }

    public void Remove()
    {
        ExceptionBuilder.CheckApiStatus(NiLibDDC.DDC_RemoveChannel(Handle));
    }
}